import pygame
import math
from typing import Tuple, List, Optional, Dict, Any


class AnimationManager:
    """动画管理器"""
    
    def __init__(self):
        self.animations = []
        self.animation_id_counter = 0
    
    def add_animation(self, animation_type: str, start_pos: Tuple[int, int], 
                     end_pos: Tuple[int, int], duration: float = 0.5, **kwargs) -> int:
        """添加动画"""
        animation_id = self.animation_id_counter
        self.animation_id_counter += 1
        
        animation = {
            'id': animation_id,
            'type': animation_type,
            'start_pos': start_pos,
            'end_pos': end_pos,
            'current_pos': start_pos,
            'duration': duration,
            'elapsed': 0.0,
            'active': True,
            **kwargs
        }
        
        self.animations.append(animation)
        return animation_id
    
    def update_animations(self, dt: float):
        """更新所有动画"""
        for animation in self.animations[:]:  # 使用切片复制避免修改列表时的问题
            if not animation['active']:
                continue
            
            animation['elapsed'] += dt
            
            # 计算进度 (0.0 到 1.0)
            progress = min(animation['elapsed'] / animation['duration'], 1.0)
            
            # 根据动画类型更新位置
            if animation['type'] == 'move':
                self._update_move_animation(animation, progress)
            elif animation['type'] == 'attack':
                self._update_attack_animation(animation, progress)
            elif animation['type'] == 'damage_flash':
                self._update_damage_flash_animation(animation, progress)
            elif animation['type'] == 'heal_flash':
                self._update_heal_flash_animation(animation, progress)
            elif animation['type'] == 'card_summon':
                self._update_card_summon_animation(animation, progress)
            elif animation['type'] == 'card_use_item':
                self._update_card_use_item_animation(animation, progress)
            elif animation['type'] == 'card_death':
                self._update_card_death_animation(animation, progress)
            elif animation['type'] == 'damage_number':
                self._update_damage_number_animation(animation, progress)
            
            # 检查动画是否完成
            if progress >= 1.0:
                animation['active'] = False
                if animation.get('on_complete'):
                    animation['on_complete']()
    
    def _update_move_animation(self, animation: dict, progress: float):
        """更新移动动画"""
        # 使用缓动函数
        eased_progress = self._ease_in_out_cubic(progress)
        
        start_x, start_y = animation['start_pos']
        end_x, end_y = animation['end_pos']
        
        current_x = start_x + (end_x - start_x) * eased_progress
        current_y = start_y + (end_y - start_y) * eased_progress
        
        animation['current_pos'] = (int(current_x), int(current_y))
    
    def _update_attack_animation(self, animation: dict, progress: float):
        """更新攻击动画(改进版)"""
        start_x, start_y = animation['start_pos']
        end_x, end_y = animation['end_pos']
        
        if progress < 0.3:
            # 阶段1: 快速冲向目标(0-0.3)
            move_progress = progress / 0.3
            eased_progress = self._ease_in_cubic(move_progress)  # 加速
            
            current_x = start_x + (end_x - start_x) * eased_progress * 0.8
            current_y = start_y + (end_y - start_y) * eased_progress * 0.8
            
        elif progress < 0.5:
            # 阶段2: 碰撞停留(0.3-0.5)
            # 保持在攻击点
            current_x = start_x + (end_x - start_x) * 0.8
            current_y = start_y + (end_y - start_y) * 0.8
            
            # 触发震动效果
            import random
            if progress < 0.35:
                shake_intensity = 5
                current_x += random.randint(-shake_intensity, shake_intensity)
                current_y += random.randint(-shake_intensity, shake_intensity)
            
        else:
            # 阶段3: 返回原位(0.5-1.0)
            return_progress = (progress - 0.5) / 0.5
            eased_progress = self._ease_out_cubic(return_progress)  # 减速
            
            attack_x = start_x + (end_x - start_x) * 0.8
            attack_y = start_y + (end_y - start_y) * 0.8
            current_x = attack_x + (start_x - attack_x) * eased_progress
            current_y = attack_y + (start_y - attack_y) * eased_progress
        
        animation['current_pos'] = (int(current_x), int(current_y))
    
    def _update_damage_flash_animation(self, animation: dict, progress: float):
        """更新伤害闪烁动画"""
        # 伤害闪烁：红色闪烁效果
        flash_intensity = math.sin(progress * math.pi * 8) * (1.0 - progress)
        animation['flash_intensity'] = max(0.0, flash_intensity)
    
    def _update_heal_flash_animation(self, animation: dict, progress: float):
        """更新治疗闪烁动画"""
        # 治疗闪烁：绿色闪烁效果
        flash_intensity = math.sin(progress * math.pi * 6) * (1.0 - progress)
        animation['flash_intensity'] = max(0.0, flash_intensity)
    
    def _update_card_summon_animation(self, animation: dict, progress: float):
        """更新卡牌召唤动画(三阶段)"""
        start_x, start_y = animation['start_pos']
        end_x, end_y = animation['end_pos']
        arc_height = animation.get('arc_height', 100)
        
        if progress < 0.2:
            # 阶段1: 手牌缩小淡出(0-0.2)
            phase_progress = progress / 0.2
            animation['scale'] = 1.0 - (phase_progress * 0.3)  # 缩小到70%
            animation['alpha'] = int(255 * (1.0 - phase_progress * 0.5))  # 淡化到50%
            animation['current_pos'] = (start_x, start_y)
        
        elif progress < 0.8:
            # 阶段2: 飞行到目标位置(0.2-0.8)
            phase_progress = (progress - 0.2) / 0.6
            
            # 恢复大小和透明度
            animation['scale'] = 0.7 + (phase_progress * 0.3)
            animation['alpha'] = int(255 * (0.5 + phase_progress * 0.5))
            
            # 抛物线轨迹
            current_x = start_x + (end_x - start_x) * phase_progress
            current_y = start_y + (end_y - start_y) * phase_progress - arc_height * math.sin(phase_progress * math.pi)
            animation['current_pos'] = (int(current_x), int(current_y))
        
        else:
            # 阶段3: 落地放大效果(0.8-1.0)
            phase_progress = (progress - 0.8) / 0.2
            animation['scale'] = 1.0 + (1.0 - phase_progress) * 0.2  # 从120%回到100%
            animation['alpha'] = 255
            animation['current_pos'] = (end_x, end_y)
    
    def _update_card_use_item_animation(self, animation: dict, progress: float):
        """更新物品使用动画(三阶段 - 延长展示时间)"""
        start_x, start_y = animation['start_pos']
        center_x = animation.get('center_x', 800)  # 默认场地中央x
        center_y = animation.get('center_y', 450)  # 默认场地中央y
        end_x, end_y = animation['end_pos']
        
        if progress < 0.25:
            # 阶段1: 从手牌飞到场地中央(0-0.25)
            phase_progress = progress / 0.25
            eased = self._ease_in_out_cubic(phase_progress)
            
            current_x = start_x + (center_x - start_x) * eased
            current_y = start_y + (center_y - start_y) * eased
            animation['scale'] = 1.0 + eased * 0.5  # 放大到150%
            animation['alpha'] = 255
            
        elif progress < 0.7:
            # 阶段2: 在中央停留展示(0.25-0.7) - 延长至1.0秒
            animation['current_pos'] = (center_x, center_y)
            animation['scale'] = 1.5
            animation['alpha'] = 255
            
            # 添加旋转效果
            rotation_progress = (progress - 0.25) / 0.45
            animation['rotation'] = rotation_progress * 360  # 旋转一圈
            
        else:
            # 阶段3: 飞向目标并消失(0.7-1.0)
            phase_progress = (progress - 0.7) / 0.3
            eased = self._ease_in_out_cubic(phase_progress)
            
            current_x = center_x + (end_x - center_x) * eased
            current_y = center_y + (end_y - center_y) * eased
            animation['current_pos'] = (int(current_x), int(current_y))
            animation['scale'] = 1.5 * (1.0 - phase_progress)  # 逐渐缩小
            animation['alpha'] = int(255 * (1.0 - phase_progress))  # 逐渐消失
    
    def _update_card_death_animation(self, animation: dict, progress: float):
        """更新卡牌死亡动画"""
        start_x, start_y = animation['start_pos']
        end_x, end_y = animation['end_pos']
        
        # 缩小效果
        scale = 1.0 - progress
        animation['scale'] = max(0.1, scale)
        
        # 移动效果
        current_x = start_x + (end_x - start_x) * progress
        current_y = start_y + (end_y - start_y) * progress
        
        animation['current_pos'] = (int(current_x), int(current_y))
        
        # 透明度效果
        alpha = 255 * (1.0 - progress)
        animation['alpha'] = max(0, int(alpha))
    
    def _update_damage_number_animation(self, animation: dict, progress: float):
        """更新伤害数字动画"""
        start_x, start_y = animation['start_pos']
        
        # 向上浮动
        float_distance = animation.get('float_distance', 50)
        current_y = start_y - float_distance * progress
        
        # 透明度变化
        alpha = 255 * (1.0 - progress)
        animation['alpha'] = max(0, int(alpha))
        
        animation['current_pos'] = (int(start_x), int(current_y))
    
    def _ease_in_out_cubic(self, t: float) -> float:
        """三次缓动函数"""
        if t < 0.5:
            return 4 * t * t * t
        else:
            p = 2 * t - 2
            return 1 + p * p * p / 2
    
    def _ease_in_cubic(self, t: float) -> float:
        """三次加速缓动"""
        return t * t * t
    
    def _ease_out_cubic(self, t: float) -> float:
        """三次减速缓动"""
        p = t - 1
        return p * p * p + 1
    
    def get_animation_position(self, animation_id: int) -> Optional[Tuple[int, int]]:
        """获取动画当前位置"""
        for animation in self.animations:
            if animation['id'] == animation_id and animation['active']:
                return animation['current_pos']
        return None
    
    def is_animation_active(self, animation_id: int) -> bool:
        """检查动画是否活跃"""
        for animation in self.animations:
            if animation['id'] == animation_id:
                return animation['active']
        return False
    
    def remove_animation(self, animation_id: int):
        """移除动画"""
        self.animations = [a for a in self.animations if a['id'] != animation_id]
    
    def clear_all_animations(self):
        """清除所有动画"""
        self.animations.clear()
    
    def get_active_animations(self) -> List[dict]:
        """获取所有活跃的动画"""
        return [a for a in self.animations if a['active']]
    
    def add_card_summon_animation(self, start_pos: Tuple[int, int], end_pos: Tuple[int, int], 
                                 duration: float = 0.8, arc_height: int = 100) -> int:
        """添加卡牌召唤动画"""
        return self.add_animation('card_summon', start_pos, end_pos, duration, arc_height=arc_height)
    
    def add_card_use_item_animation(self, start_pos: Tuple[int, int], end_pos: Tuple[int, int], 
                                   duration: float = 1.2) -> int:
        """添加物品使用动画（延长展示时间）"""
        return self.add_animation('card_use_item', start_pos, end_pos, duration)
    
    def add_card_death_animation(self, start_pos: Tuple[int, int], end_pos: Tuple[int, int], 
                                 duration: float = 1.0) -> int:
        """添加卡牌死亡动画"""
        return self.add_animation('card_death', start_pos, end_pos, duration)
    
    def add_damage_number_animation(self, start_pos: Tuple[int, int], damage: int, 
                                      duration: float = 1.5, float_distance: int = 50) -> int:
        """添加伤害数字动画"""
        return self.add_animation('damage_number', start_pos, start_pos, duration, 
                                 damage=damage, float_distance=float_distance)
    
    def add_animation_with_card_data(self, animation_type: str, start_pos: Tuple[int, int], 
                                   end_pos: Tuple[int, int], card_data: Dict[str, Any], 
                                   duration: float = 0.8) -> int:
        """添加带有卡牌数据的动画"""
        return self.add_animation(animation_type, start_pos, end_pos, duration, card_data=card_data)


class AttackAnimation:
    """攻击动画类"""
    
    def __init__(self, attacker_pos: Tuple[int, int], target_pos: Tuple[int, int], 
                 duration: float = 0.8):
        self.attacker_pos = attacker_pos
        self.target_pos = target_pos
        self.duration = duration
        self.elapsed = 0.0
        self.active = True
        
        # 计算攻击路径
        self.attack_point = self._calculate_attack_point(attacker_pos, target_pos)
    
    def _calculate_attack_point(self, start: Tuple[int, int], end: Tuple[int, int]) -> Tuple[int, int]:
        """计算攻击点（目标附近）"""
        dx = end[0] - start[0]
        dy = end[1] - start[1]
        distance = math.sqrt(dx * dx + dy * dy)
        
        # 攻击到目标附近（距离的80%）
        attack_distance = distance * 0.8
        
        if distance > 0:
            attack_x = start[0] + (dx / distance) * attack_distance
            attack_y = start[1] + (dy / distance) * attack_distance
        else:
            attack_x, attack_y = end
        
        return (int(attack_x), int(attack_y))
    
    def update(self, dt: float) -> Tuple[int, int]:
        """更新动画，返回当前位置"""
        if not self.active:
            return self.attacker_pos
        
        self.elapsed += dt
        progress = min(self.elapsed / self.duration, 1.0)
        
        if progress < 0.5:
            # 前半段：移动到攻击点
            move_progress = progress * 2
            eased_progress = self._ease_in_out_cubic(move_progress)
            
            current_x = self.attacker_pos[0] + (self.attack_point[0] - self.attacker_pos[0]) * eased_progress
            current_y = self.attacker_pos[1] + (self.attack_point[1] - self.attacker_pos[1]) * eased_progress
        else:
            # 后半段：返回原位
            return_progress = (progress - 0.5) * 2
            eased_progress = self._ease_in_out_cubic(return_progress)
            
            current_x = self.attack_point[0] + (self.attacker_pos[0] - self.attack_point[0]) * eased_progress
            current_y = self.attack_point[1] + (self.attacker_pos[1] - self.attack_point[1]) * eased_progress
        
        if progress >= 1.0:
            self.active = False
        
        return (int(current_x), int(current_y))
    
    def _ease_in_out_cubic(self, t: float) -> float:
        """三次缓动函数"""
        if t < 0.5:
            return 4 * t * t * t
        else:
            p = 2 * t - 2
            return 1 + p * p * p / 2
    
    def is_complete(self) -> bool:
        """检查动画是否完成"""
        return not self.active


class DamageFlash:
    """伤害闪烁效果"""
    
    def __init__(self, duration: float = 0.5):
        self.duration = duration
        self.elapsed = 0.0
        self.active = True
    
    def update(self, dt: float) -> float:
        """更新闪烁，返回闪烁强度 (0.0 到 1.0)"""
        if not self.active:
            return 0.0
        
        self.elapsed += dt
        progress = min(self.elapsed / self.duration, 1.0)
        
        # 快速闪烁效果
        flash_intensity = math.sin(progress * math.pi * 8) * (1.0 - progress)
        
        if progress >= 1.0:
            self.active = False
        
        return max(0.0, flash_intensity)
    
    def is_complete(self) -> bool:
        """检查动画是否完成"""
        return not self.active


class HealFlash:
    """治疗闪烁效果"""
    
    def __init__(self, duration: float = 0.6):
        self.duration = duration
        self.elapsed = 0.0
        self.active = True
    
    def update(self, dt: float) -> float:
        """更新闪烁，返回闪烁强度 (0.0 到 1.0)"""
        if not self.active:
            return 0.0
        
        self.elapsed += dt
        progress = min(self.elapsed / self.duration, 1.0)
        
        # 温和的绿色闪烁效果
        flash_intensity = math.sin(progress * math.pi * 6) * (1.0 - progress)
        
        if progress >= 1.0:
            self.active = False
        
        return max(0.0, flash_intensity)
    
    def is_complete(self) -> bool:
        """检查动画是否完成"""
        return not self.active
